# -*- coding: utf8 -*-

from plugmgr import plugin
from twisted.python.log import msg, err

__all__ = ["cmd"]

class alreadyRegistered(Exception):
    pass

class command:
    """Instance of this class will be passed to command handlers
    they should use .args, .source, .reply, .access, .err"""
    def __init__(self, bot, type, source, body, lang):
        self.bot = bot
        self.lang = lang
        if body.count(' '):
            n = body.find(' ')
            self.cmd, self.args = body[:n], body[n+1:]
        else:
            self.cmd, self.args = body, None
        self.type, self.source = type, source
    def reply(self, msg):
        if self.bot.has("muc"): self.bot["muc"].sendMessage(self.type, self.source, msg)
        else: self.bot["stanzas"].sendMessage("chat", self.source, msg)
    def access(self):
        if self.bot.has("access"): return self.bot["access"].get(self.source)
        else: return 0
    def _(self, msg):
        if self.bot.has("lang"): return self.bot["lang"].get(msg, self.lang)
        else: return msg
    def err(self):
        self.reply(self._("An error occured while processing your command. Please contact with administrator, or see log for details if you are administrator."))
        err()

class cmd(plugin):
    requires = ["stanzas", "config", "events"]
    def __init__(self, bot):
        # \todo: how to do it in one xpath instead of three?
        self.bot = bot
        self.bot["config"].setdefault("cmd_prefix", "/", 0, 9)
        self.bot["config"].setdefault("lang", "detect, en", 0, 9)
        self.cmdHandlers = {}
        # на всякий случай... если кто-то забудет какой префикс поставил, то посмотрит в логе
        msg("Command plugin loaded with prefix='%s'" % str(self.bot["config"]["cmd_prefix"]))
        self.mesHandlerId = self.bot['events'].registerHandler('message',self.messageHandler)
    def unload(self):
        self.bot['events'].removeHandler('message',self.mesHandlerId)
    def messageHandler(self,source,type,body,lang):
        prefix = self.bot["config"][(source, "cmd_prefix")]
        if body.startswith(prefix):
            cmd = command(self.bot, type, source, body[len(prefix):], lang)
            self.callCmdHandlers(cmd)
    def callCmdHandlers(self, cmd):
        access = cmd.access()
        if access < 0: return
        item = self.cmdHandlers.get(cmd.cmd, None)
        if item:
            handler, required_access = item
            if access >= required_access:
                try: handler(cmd)
                except: cmd.err()
            else:
                cmd.reply(cmd._("Access denied."))
    def addHandler(self, command, handler, required_access=0):
        if self.cmdHandlers.has_key(command): raise alreadyRegistered, self.cmdHandlers[command]
        self.cmdHandlers[command] = (handler, required_access)
    def removeHandler(self, *commands):
        map(self.cmdHandlers.pop, commands)
